package com.stm.bi.report.productTrend;


import com.stm.bi.core.util.DateUtils;
import com.stm.bi.core.util.ETLUtils;
import com.stm.bi.core.util.SqlUtils;
import com.stm.bi.dto.query.DimensionDataGroupQry;
import com.stm.bi.dto.query.GroupField;
import com.stm.bi.dto.query.ods.OdsListQry;
import com.stm.bi.repository.dataobject.ods.OdsWarehouseDO;
import com.stm.bi.repository.ods.OdsWarehouseRepository;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.dbcp.JdbcService;
import com.stm.framework.dto.Response;
import com.stm.ucenter.api.DeptRemoteService;
import com.stm.ucenter.dto.query.org.DeptListQry;
import com.stm.ucenter.dto.vo.org.DeptVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.*;

import static com.stm.bi.constant.DimensionConstants.*;
import static com.stm.bi.constant.IndexConstants.*;
import static com.stm.bi.constant.PlanConstants.*;

@Component
public class ProductDataQueryExe {

    @Resource
    private JdbcService jdbcService;
    @Resource
    private DeptRemoteService deptRemoteService;
    @Resource
    private OdsWarehouseRepository odsWarehouseRepository;
    private static final Long RETURN_QTY_INDEX_ID = 8531980289704192L;

    public static final Integer DELAY = 2;



    public static List<String> getProdCodeAndName(Long dimensionId) {

        if (CATEGORY_DIMENSION_IDS.contains(dimensionId)) {
            return List.of(CATEGORY_CODE_FIELD, CATEGORY_NAME_FIELD);
        } else if (ASSORTMENT_DIMENSION_IDS.contains(dimensionId)) {
            return List.of(ASSORTMENT_CODE_FIELD, ASSORTMENT_NAME_FIELD);
        } else if (STYLE_DIMENSION_IDS.contains(dimensionId)) {
            return List.of(STYLE_CODE_FIELD, STYLE_NAME_FIELD);
        } else {
            return List.of(STYLE_TYPE_FIELD, STYLE_TYPE_NAME_FIELD);
        }
    }


    public List<Map> selectInventoryData(DimensionDataGroupQry qry, String code, List<Map> data){
        return selectInventoryData(qry, code, data, new ArrayList<>());
    }

    /**
     * 获取入仓数，起初库存，期末库存等数据
     */
    public List<Map> selectInventoryData(DimensionDataGroupQry qry, String code, List<Map> data, List<String> dateList) {

        List<String> groupBy = qry.getGroupBy() == null ? Arrays.asList(code, DATE_FIELD) : qry.getGroupBy();

        //设置查询类并查询
        DimensionDataGroupQry inventoryQry = new DimensionDataGroupQry()
                .setOrgNo(qry.getOrgNo())
                .setStartDate(qry.getStartDate())
                .setEndDate(qry.getEndDate())
                .setDeptId(qry.getDeptId())
                .setDateType(qry.getDateType())
                .setGroupBy(groupBy)
                .setOtherConditions(qry.getOtherConditions());

        List<GroupField> inventoryGroupFields = new ArrayList<>(Arrays.asList(
                GroupField.of(NUMBER_OF_WAREHOUSING_FIELD_NAME, "sum"),
                GroupField.of(INVENTORY_FIELD, "sum"),
                GroupField.of(OPENING_INVENTORY_FIELD_NAME, "sum")
        ));

        inventoryQry.setGroupFields(inventoryGroupFields);

        Long deptId = qry.getDeptId();
        Map<Long, Long> deptIdMap = getDeptIdMap(UserHolder.getOrgId(), qry.getOrgNo());

        if (deptIdMap.containsKey(deptId)) {
            deptId = deptIdMap.get(deptId);
        }

        inventoryQry.setDeptId(deptId);
        String sql = SqlUtils.buildSql(inventoryQry, "ads_base_product_inventory");

        List<Map> maps = jdbcService.selectList(sql, new Object[]{});

        return setInventoryData(qry, data, dateList, code, maps);
    }

    private Map<Long, Long> getDeptIdMap(Long orgId, String orgNo) {
        //仓库与部门的对应关系逻辑
        Response<List<DeptVO>> deptResp = deptRemoteService.selectList(new DeptListQry().setOrgId(orgId));
        if (!deptResp.isSuccess()) {
            return new HashMap<>();
        }

        List<DeptVO> depts = deptResp.getData();
        Map<Long, Long> deptMap = new HashMap<>();
        depts.forEach(d -> deptMap.put(d.getId(), d.getParentId()));

        List<OdsWarehouseDO> warehouses = odsWarehouseRepository.selectList(new OdsListQry().setOrgNo(orgNo));
        List<Long> deptIds = warehouses.stream().map(OdsWarehouseDO::getDeptId).filter(Objects::nonNull).toList();

        //获取对应的仓库部门对应关系MAP
        return ETLUtils.getWarehouseDeptIdMap(deptMap, deptIds);
    }

    // 设置库存数据
    private  List<Map> setInventoryData(DimensionDataGroupQry qry, List<Map> data, List<String> dateList, String code, List<Map> maps) {

        if(dateList == null || dateList.isEmpty()){
            if(data.isEmpty()){
                return maps;
            }
            setInventoryIntoData(data, maps, code);
        }else {
            String s = selectMaxInventoryDate(dateList.getFirst(), dateList.getLast(), qry.getDateType());

            Map maxMap = new HashMap();
            Map<String, Map> maxKeyMap = new HashMap<>();
            List<String> keys = new ArrayList<>();
            if(code != null){
                keys = maps.stream()
                        .map(m -> (String) m.get(code))
                        .distinct()
                        .toList();
            }

            for(String date: dateList){
                if(date.length() == 7 && TYPE_WEEK.equals(qry.getDateType())){
                    date = DateUtils.getWeekFirstDay(date);
                }
                String finalDate = date;

                if(date.compareTo(s) >= 0){
                    if(code == null){
                        Optional<Map> any = maps.stream()
                                .filter(m -> m.get(DATE_FIELD).equals(finalDate))
                                .findAny();
                        if(any.isPresent()){
                            maxMap = any.get();
                        }else {
                            Map newMap = new HashMap(maxMap);
                            newMap.put(DATE_FIELD, finalDate);
                            maps.add(newMap);
                        }
                    }else {
                        for(String k: keys){
                            Optional<Map> any = maps.stream()
                                    .filter(m -> m.get(code).equals(k) && m.get(DATE_FIELD).equals(finalDate))
                                    .findAny();
                            if(any.isPresent()){
                                maxKeyMap.put(k, any.get());
                            }else {
                                Map newMap;
                                if(maxKeyMap.get(k) == null){
                                    newMap = new HashMap();
                                    newMap.put(code, k);
                                }else {
                                    newMap = new HashMap(maxKeyMap.get(k));
                                }
                                newMap.put(DATE_FIELD, finalDate);

                                maps.add(newMap);
                            }
                        }
                    }
                }
            }

            if(data.isEmpty()){
                return maps;
            }

            setInventoryIntoData(data, maps, code);
        }
        return data;
    }

    private void setInventoryIntoData(List<Map> data, List<Map> maps, String finalKey) {
        for(Map m: maps){
            Optional<Map> first = data.stream()
                    .filter(m1 -> {
                        if (m1.get(finalKey) == null && m1.get(DATE_FIELD) == null) {
                            return true;
                        } else if (m1.get(DATE_FIELD) == null) {
                            return m1.get(finalKey).equals(m.get(finalKey));
                        } else if (m1.get(finalKey) == null) {
                            return m1.get(DATE_FIELD).equals(m.get(DATE_FIELD));
                        } else {
                            return m1.get(finalKey).equals(m.get(finalKey)) && m1.get(DATE_FIELD).equals(m.get(DATE_FIELD));
                        }
                    })
                    .findFirst();

            if(first.isPresent()){
                first.get().put(INVENTORY_FIELD, m.get(INVENTORY_FIELD));
                first.get().put(NUMBER_OF_WAREHOUSING_FIELD_NAME, m.get(NUMBER_OF_WAREHOUSING_FIELD_NAME));
                first.get().put(OPENING_INVENTORY_FIELD_NAME, m.get(OPENING_INVENTORY_FIELD_NAME));
            }else {
                data.add(m);
            }
        }
    }

    public String selectMaxInventoryDate(String startData, String endDate, String dateType){

        String sql = "select max(date) as date from ads_base_product_inventory";
        if(startData != null && endDate != null){
            sql = "select max(date) as date from ads_base_product_inventory where date >= '" + startData + "' and date <= '" + endDate + "'" + " and date_type = '" + dateType + "'";
        }else {
            sql = "select max(date) as date from ads_base_product_inventory where date_type = '" + dateType + "'";
        }
        String date;
        List<Map> maps = jdbcService.selectList(sql, new Object[]{});
        if(maps.isEmpty()){
            date = startData;
        }else {
            Map map = maps.getFirst();
            date = map.get(DATE_FIELD) == null ? startData : (String) map.get(DATE_FIELD);
        }

        if(date != null){
            if(TYPE_YEAR.equals(dateType)){
                date = date.substring(0, 4);
            }else if(TYPE_MONTH.equals(dateType)){
                date = date.substring(0, 7);
            }else if(TYPE_DAY.equals(dateType)){
                date = date.substring(0, 10);
            }
        }

        return date;
    }

//    public DimensionTableDataVO styleQtyDayProcessTable(ReportQry reportQry){
//        DimensionTableDataVO table = new DimensionTableDataVO();
//        List<TitleVO> title = new ArrayList<>();
//        List<ValueVO> sumData = new ArrayList<>();
//        List<Map<String, String>> data = new ArrayList<>();
//
//        List<String> dateList = DateUtils.getDateList(reportQry.getStartDate(), reportQry.getEndDate(), reportQry.getDateType().getValue());
//
//        Collections.reverse(dateList);
//
//        DimensionDataGroupQry qry = new DimensionDataGroupQry()
//                .setDimensionId(reportQry.getDimensionId())
//                .setDeptId(reportQry.getDeptId())
//                .setDateType(reportQry.getDateType().getValue())
//                .setStartDate(reportQry.getStartDate())
//                .setEndDate(reportQry.getEndDate())
//                .setGroupBy(Arrays.asList(BUSINESS_ID_FIELD_NAME, PRODUCT_STYLE_FIELD_NAME))
//                .setGroupFields(Collections.singletonList(new GroupField().setFieldName(QTY_FIELD).setGroupType("sum")))
//                .setOrderBy(QTY_FIELD);
//
//        List<Map> maps = dimensionDataQueryExe.selectListBySql(qry);
//
//        List<Map> finalMaps;
//        if(reportQry.getPageNum() == 1){
//
//            qry.setGroupBy(Collections.singletonList(DATE_FIELD));
//
//            List<Map> totalMap = dimensionDataQueryExe.selectListBySql(qry);
//
//            Map<String, String> total = new HashMap();
//            total.put(PRODUCT_STYLE_FIELD_NAME, "合计");
//            BigDecimal sumQty = BigDecimal.ZERO;
//            for(String date: dateList){
//                Map map = totalMap.stream()
//                        .filter(m -> m.get(DATE_FIELD).equals(date))
//                        .findAny().orElse(new HashMap());
//
//                BigDecimal qty = map.get(QTY_FIELD) == null ? BigDecimal.ZERO : (BigDecimal) map.get(QTY_FIELD);
//
//                sumQty = sumQty.add(qty);
//                total.put(date, map.get(QTY_FIELD) == null ? null : ((BigDecimal)map.get(QTY_FIELD)).setScale(0, RoundingMode.HALF_UP) + "");
//            }
//            total.put("total", sumQty.setScale(0, RoundingMode.HALF_UP) + "");
//            data.add(total);
//            finalMaps = maps.subList(0, Math.min(maps.size(), reportQry.getPageSize() - 1));
//        }else {
//            finalMaps = maps.subList(
//                    Math.min(maps.size(), (reportQry.getPageNum() - 1) * reportQry.getPageSize() - 1),
//                    Math.min(maps.size(), reportQry.getPageNum() * reportQry.getPageSize() - 1)
//            );
//        }
//
//        qry.setGroupBy(null)
//                .setGroupFields(null)
//                .setOrderBy(null);
//
//        List<Map> detailMaps = dimensionDataQueryExe.selectListBySql(qry);
//
//        title.add(new TitleVO().setCode(PRODUCT_STYLE_FIELD_NAME).setName("款式"));
//        for(String date: dateList){
//            TitleVO t = new TitleVO();
//            t.setCode(date).setName(date.substring(5,10));
//            title.add(t);
//        }
//
//        title.add(new TitleVO().setCode("total").setName("合计销量"));
//
//        for(Map m: finalMaps){
//            Map<String, String> map = new HashMap();
//            map.put(PRODUCT_STYLE_FIELD_NAME, m.get(PRODUCT_STYLE_FIELD_NAME) + "");
//            for(String date: dateList){
//
//                Map dateMap = detailMaps.stream()
//                        .filter(d -> d.get(DATE_FIELD).equals(date))
//                        .filter(d -> Objects.equals(d.get(BUSINESS_ID_FIELD_NAME), m.get(BUSINESS_ID_FIELD_NAME)))
//                        .findAny().orElse(new HashMap());
//
//                if (dateMap.get(QTY_FIELD) == null) {
//                    map.put(date, null);
//                } else {
//                    map.put(date, ((BigDecimal)dateMap.get(QTY_FIELD)).setScale(0, RoundingMode.HALF_UP) + "");
//                }
//            }
//
////            BigDecimal qty = m.get(QTY_FIELD) == null ? BigDecimal.ZERO : (BigDecimal) m.get(QTY_FIELD);
//
//            map.put("total", m.get(QTY_FIELD) == null ? null : ((BigDecimal)m.get(QTY_FIELD)).setScale(0, RoundingMode.HALF_UP) + "");
//
//            data.add(map);
//        }
//
//        BigDecimal totalQty = maps.stream()
//                .map(map -> (BigDecimal)map.get(QTY_FIELD))
//                .filter(Objects::nonNull)
//                .reduce(BigDecimal::add)
//                .orElse(BigDecimal.ZERO)
//                .setScale(0, RoundingMode.HALF_UP);
//
//        sumData.add(new ValueVO().setCode("total").setName("合计销量(件)").setValue(totalQty));
//
//        table.setDatas(data);
//        table.setTitle(title);
//        table.setSumData(sumData);
//        table.setSize(reportQry.getPageSize());
//        table.setCurrent(reportQry.getPageNum());
//        table.setTotal(maps.size() + 1);
//
//        return table;
//    }


}
